import { InjectRepository } from "@nestjs/typeorm";
import { UserRepositoryAbstract } from "../user-abstract.repository";
import { User } from "../entities/user.entity";
import { Repository } from "typeorm";
import { Inject } from "@nestjs/common";
import { PRISMA_DATABASE } from "@/database/database.constants";
import { PrismaClient } from "@prisma/client";
import argon2 from "argon2";

export class PrismaRepository extends UserRepositoryAbstract {
    constructor(@Inject(PRISMA_DATABASE) private readonly prismaClient: PrismaClient,) {
        super();
    }

    findAll(page: number = 10, limit: number = 1): Promise<any[]> {
        const skip = (page - 1) * limit;
        return this.prismaClient.user.findMany({ skip, take: limit });
    }

    find(username?: string): Promise<any[]> {
        return this.prismaClient.user.findMany({ where: { username } })
    }

    findOne(username?: string): Promise<any> {
        return this.prismaClient.user.findUnique({
            where: { username }, include: {
                UserRole: {
                    include: {
                        Role: {
                            include: { RolePermission: true }
                        }
                    }
                }
            }
        });
    }

    async create(userObj: any): Promise<any[]> {
        // 读取默认角色信息
        const default_role_id = 1;
        // 判断角色信息是否在数据库中
        // 写入角色与用户关系表，并创建用户
        // return this.prismaClient.user.create({ data: userObj })
        return await this.prismaClient.$transaction(async (prisma: PrismaClient) => {
            const roleIds = userObj && userObj.roleIds ? userObj.roleIds : [default_role_id]
            const valiRoleIds: any = [];

            for (const roleId of roleIds) {
                const role = await prisma.role.findUnique({
                    where: { id: roleId }
                });

                if (role) {
                    valiRoleIds.push(roleId);
                }
            }

            if (valiRoleIds.length == 0) {
                valiRoleIds.push(default_role_id);
            }

            return prisma.user.create({
                data: {
                    ...userObj,
                    UserRole: {
                        create: valiRoleIds.map((roleId: any) => ({ roleId }))
                    }
                }
            })
        })
    }

    async update(userObj: any): Promise<any> {
        /* return await this.prismaClient.user.update({
            where: { id: userObj.id },
            data: userObj
        }) */

        return await this.prismaClient.$transaction(async (prisma: PrismaClient) => {
            const { id, name, password, roles, ...rest } = userObj;
            // 更新的where条件
            const whereCond = id ? { id } : { name };
            let updateData: any = {};
            if (password) {
                const newHashPass = await argon2.hash(password);
                updateData.password = newHashPass;
            }

            updateData = { ...updateData, ...rest };

            const roleIds = [];
            
            await Promise.all(roles.map(async (role: any) => {
                const { permissions, ...restRole } = role
                await prisma.role.update({
                    where: { id: role.id },
                    data: {
                        ...restRole,
                        RolePermissions: {
                            deleteMany: {},       // 这样可以删除所有数据
                            create: (permissions || []).map((permission: any) => ({
                                permission: {
                                    connectOrCreate: {
                                        where: {
                                            name: permission.name,
                                        },
                                        create: permission,
                                    }
                                }
                            }))
                        }
                    }
                })
            }));

            // 用户 角色更新
            const updatedUser = await prisma.user.update({
                where: whereCond,
                data: {
                    ...updateData,
                    UserRole: {
                        deleteMany: {},       // 这样可以删除所有数据
                        create: (roleIds || []).map((role: any) => ({ roleId: role.id }))
                    }
                },
                include: {
                    UserRole: true,
                }
            });

            return updatedUser;
        })
    }
    delete(id: string): Promise<any[]> {
        return this.prismaClient.user.delete({ where: { id } })
    }

}